﻿using Pay.IService;
using Pay.DTO.hniao;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Pay.Core;
using Pay.DTO;
using Newtonsoft.Json.Linq;
using Pay.TO;

namespace Pay.Service {
    public class HniaoMallService : ServiceBase, IHniaoService, IDisposable {
        /// <summary>
        /// 
        /// </summary>
        private IUnitOfWork _iUnitOfWork;
        private IMerchantService _iMerchantService;
        private IOrderService _iOrderService;
        private IProductService _iProductService;
        private HniaoMallSign _hnMallSign;
        private IPayHtmlService _iPayhtmlService;
        public HniaoMallService(IUnitOfWork iUnitOfWork, IPayHtmlService iPayHtmlService,
                                IMerchantService iMerchantService, IOrderService iOrderService,
                                IProductService iProductService) : base(iUnitOfWork) {
            _hnMallSign = new HniaoMallSign();
            _iPayhtmlService = iPayHtmlService;
            _iUnitOfWork = iUnitOfWork;
            _iMerchantService = iMerchantService;
            _iOrderService = iOrderService;
            _iProductService = iProductService;
        }
        /// <summary>
        /// 获取商品列表数据
        /// </summary>
        /// <param name="goods_req"></param>
        /// <returns></returns>
        public async Task<int> GetGoodsList(hn_goods_list_req goods_req) {
            var products = new List<Data.Product>();
            var merchant = context.Merchants.FirstOrDefault(c => c.MerchantNo == RequestMethod.TOKEN_NO);
            var hn_result = await _hnMallSign.HniaoReq<hn_goods_list_res>(goods_req);
            if (hn_result.code == "0") {
                foreach (var goods in hn_result.data.goodsList) {
                    bool is_exist = context.Products.Any(c => c.IsHtl == 2 && c.Sku == goods.sku && c.MerchantId == merchant.Id);
                    if (is_exist) continue;
                    var unixTime = DateTime.Now.ToUnix();
                    var product = new Data.Product {
                        MerchantId = merchant.Id,
                        Sku = goods.sku,
                        Props = "[]",
                        TradeType = goods.tradeType,
                        Code = goods.barcode,
                        Name = goods.goodsName,
                        Description = goods.description,
                        BrandsName = goods.brand,
                        Country = goods.origin,
                        SaleStatus = SaleStatus.Sell,
                        AuditStatus = AuditStatus.PendingAudit,
                        IsHtl = 2,
                        CreateTime = unixTime,
                        UpdateTime = unixTime
                    };
                    product.ImagePath = (product.MainImageUrl = string.IsNullOrEmpty(goods.big) ? "" : string.Format("[\"http://www.houniao.hk/{0}\"]", goods.big));
                    if (goods.spec != null) {
                        var item = JObject.Parse(goods.spec.ToJson());
                        var collection = item.ToObject<SortedDictionary<string, object>>();
                        foreach (var kv in collection) {
                            if (kv.Value is JArray) {
                                var arrs = kv.Value as JArray;
                                foreach (var spec in arrs) {
                                    var goods_spec = spec.ToObject<hn_goods_spec>().ToDtoObject<Data.ProductSku>();
                                    goods_spec.Product = product;
                                    string sku_value = System.Text.RegularExpressions.Regex.Replace(goods_spec.SkuName, @"[^0-9]+", "");
                                    goods_spec.SkuPath = string.Format("{0}-{1}", goods.sku, sku_value);
                                    product.ProductSkus.Add(goods_spec);
                                }
                            }
                        }
                        var firstSpec = product.ProductSkus.FirstOrDefault();
                        product.Price = product.MarketPrice = firstSpec.Price;
                        product.CostPrice = firstSpec.Price;
                        product.Stock = firstSpec.Stock;
                        products.Add(product);
                    }
                }
                if (products.Count > 0) {
                    context.Products.AddRange(products);
                }
            }
            int result = _iUnitOfWork.Commit("goods");
            return 0;
        }

        public async Task<int> GetProductStock() {
            var products = context.Products.Where(c => c.MerchantId == 111611).ToList();
            foreach (var row in products) {
                int sum = 0;
                var product = context.Products.FirstOrDefault(c => c.Id == row.Id);
                var hn_stock_result = await _hnMallSign.HniaoReq<hn_product_stock_res>(new hn_product_stock_req { goodsSku = row.Sku });
                if (hn_stock_result.code == "0") {
                    foreach (var spec in hn_stock_result.data) {
                        sum += spec.stockNum;
                        foreach (var p_spec in product.ProductSkus) {
                            if (string.IsNullOrEmpty(spec.startExpDate)) {
                                p_spec.Stock = spec.stockNum;
                            }
                            if (p_spec.StartExpDate == spec.startExpDate && p_spec.EndExpDate == spec.endExpDate) {
                                p_spec.Stock = spec.stockNum;
                            }
                        }
                    }
                    product.Stock = sum;
                    try {
                        int reuslt = _iUnitOfWork.Commit("Products");
                    } catch {

                    }

                }
            }
            return 0;
        }

        public async Task<int> GetGoodsListByCatId() {
            var hn_cat_result = await _hnMallSign.HniaoReq<hniao_category_res>(new hniao_category_req { });
            if (hn_cat_result.code == "0") {
                foreach (var express in hn_cat_result.data) {
                    try {
                        int result = await get_childens(express.children);
                    } catch{

                    }

                }
            }
            return 0;
        }

        private async Task<int> get_childens(List<hn_children> childrens) {
            var merchant = context.Merchants.FirstOrDefault(c => c.MerchantNo == RequestMethod.HNIAO_NO);
            foreach (var children in childrens) {
                var products = new List<Data.Product>();
                await HnReqGoodsList(products, children, merchant);
                if (products.Count > 0) {
                    context.Products.AddRange(products);
                }
                int reuslt = _iUnitOfWork.Commit("Products");
                if (children.children.Count > 0)
                    await get_childens(children.children);
            }
            return 0;
        }

        private async Task<int> HnReqGoodsList(List<Data.Product> products, hn_children children, Data.Merchant merchant) {
            var req_data = new hn_category_goods_req {
                page = 1,
                categoryId = children.catId
            };
            var hn_goods_result = await _hnMallSign.HniaoReq<hn_category_goods_res>(req_data);
            if (hn_goods_result.data == null) return 0;
            AddProduct(products, hn_goods_result.data.goodsList, merchant);
            if (hn_goods_result.data.total <= 50)
                return 0;
            int times = hn_goods_result.data.total / 50 + (hn_goods_result.data.total % 50 > 0 ? 1 : 0);
            for (int i = 2; i <= times; i++) {
                req_data.page = i;
                hn_goods_result = await _hnMallSign.HniaoReq<hn_category_goods_res>(req_data);
                if (hn_goods_result.data == null) return 0;
                AddProduct(products, hn_goods_result.data.goodsList, merchant);
            }

            return 0;
        }

        private void AddProduct(List<Data.Product> products, List<hn_category_goodsList_res> goodsList, Data.Merchant merchant) {
            foreach (var goods in goodsList) {
                bool is_exist = context.Products.Any(c => c.IsHtl == 2 && c.Sku == goods.sku && c.MerchantId == merchant.Id);
                if (is_exist) {
                    var row = context.Products.FirstOrDefault(c=>c.Sku ==  goods.sku && c.MerchantId == merchant.Id);
                    row.Name = goods.goodsName;
                    continue;
                }
                var unixTime = DateTime.Now.ToUnix();
                var product = new Data.Product {
                    MerchantId = merchant.Id,
                    Sku = goods.sku,
                    Props = "[]",
                    TradeType = goods.tradeType,
                    Code = goods.barcode,
                    Name = goods.goodsName,
                    Description = string.IsNullOrEmpty(goods.description) ? "" : StringHelper.StringToImgUrl(WebHelper.HtmlDecode(goods.description), RequestMethod.HNIAO_DOMAIN),
                    BrandsName = goods.brand,
                    Country = goods.origin,
                    SaleStatus = SaleStatus.OutOfStock,
                    AuditStatus = AuditStatus.PendingAudit,
                    IsHtl = 2,
                    CreateTime = unixTime,
                    UpdateTime = unixTime
                };
                product.ImagePath = (string.IsNullOrEmpty(goods.big) ? "" : string.Format("[\"{0}/{1}\"]", RequestMethod.HNIAO_DOMAIN, goods.big));
                product.MainImageUrl = (string.IsNullOrEmpty(goods.big) ? "" : string.Format("{0}/{1}", RequestMethod.HNIAO_DOMAIN, goods.big));
                if (goods.spec != null) {
                    decimal max_price = 0;
                    var item = JObject.Parse(goods.spec.ToJson());
                    var collection = item.ToObject<SortedDictionary<string, object>>();
                    foreach (var kv in collection) {
                        if (kv.Value is JArray) {
                            var arrs = kv.Value as JArray;
                            foreach (var spec in arrs) {
                                var goods_spec = spec.ToObject<hn_goods_spec>();
                                if (goods_spec.specPrice > max_price && goods_spec.specNum == 1) {
                                    product.Price = goods_spec.specPrice * 1.2M;
                                    product.CostPrice = goods_spec.specPrice;
                                    product.Stock = goods_spec.stock;
                                    max_price = goods_spec.specPrice;
                                }
                            }
                        }
                    }
                    products.Add(product);
                }
            }
        }
        /// <summary>
        /// 接收候鸟推送数据
        /// </summary>
        /// <param name="notify"></param>
        /// <returns></returns>
        public async Task<int> PullGoods(hn_notify_base notify) {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("候鸟推送数据验签校验成功......");
            var orderNo = string.Format("H{0}", DtoHelper.GenerateOrderNumber());
            var pay_html = new pay_html_dto {
                html = notify.ToJson(),
                merchant_no = RequestMethod.TOKEN_NO,
                create_time = DateTime.Now,
                order_no = orderNo,
                charge = notify.ToJson(),
                pay_type = RequestMethod.TOKEN_HNIAO_DATA,
                is_finish = 0,
                id = orderNo
            };
            var hniaoReturn = await HniaoLogicFade.AnalysisLogic(pay_html, context);
            var result = _iPayhtmlService.Save(pay_html, hniaoReturn.tag);
            if (hniaoReturn.is_push) {
                var jPushHelp = new JPushHelp(t_RequestMethod.push_app_key, t_RequestMethod.push_app_secret);
                foreach (var message in hniaoReturn.messages) {
                    jPushHelp.Push(message.title, message.content, (int)message.type, message.object_id.Value, new List<string> { message.short_content });
                }
            }
            return 0;
        }
        /// <summary>
        /// 解析候鸟推送数据
        /// </summary>
        public void AnalysisProducts() {
            //var log = IocHelper.Get<ILogHelper>("info");
            //log.Info("候鸟解析数据业务处理中...");
            //var pay_htmls = _iPayhtmlService.GetPayHtmls(RequestMethod.TOKEN_HNIAO_DATA);
            //foreach (var pay_html in pay_htmls) {
            //    HniaoLogicFade.AnalysisLogic(pay_html, context, _iUnitOfWork);
            //}
        }
        /// <summary>
        /// 推送订单
        /// </summary>
        /// <returns></returns>
        public async Task<int> PushOrder() {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("候鸟订单推送中...");
            int result = 0;
            var pay_htmls = _iPayhtmlService.GetPayHtmls(RequestMethod.TOKEN_HNIAO_ORDER);
            foreach (var pay_html in pay_htmls) {
                var ord_html = pay_html.html.ToObject<Data.Order>();
                var regions = ord_html.Shipping.RegionName.Split(' ');
                var hnOrders = new List<hn_order>();
                var html = context.PayHtmls.FirstOrDefault(c => c.OrderNo == pay_html.order_no);
                bool stop = context.Orders.Any(c=>c.OrderNo == ord_html.OrderNo && c.PushStatus == OrderPushStatus.PushForbid);
                if (stop) {
                    html.IsFinish = 1;
                    continue;
                }
                var order = new hn_order {
                    userName = ord_html.Shipping.RealName,
                    IDCard = ord_html.Shipping.IdCard,
                    userAddress = ord_html.Shipping.Address,
                    userPhone = ord_html.Shipping.Phone,
                    province = regions[0],
                    city = regions[1],
                    district = (regions.Length == 3 ? regions[2] : ""),
                    realTotalMoney = ord_html.PayAmount,
                    createTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    cusOrderNo = ord_html.OrderNo,
                    goodsMoney = ord_html.OrderAmount,
                    deliverMoney = 0
                };
                foreach (var order_item in ord_html.OrderItems) {
                    var product = context.Products.FirstOrDefault(c => c.Id == order_item.ProductId);
                    if (string.IsNullOrEmpty(product.Sku)) {
                        pay_html.is_finish = 2;
                        continue;
                    }
                    var req = new hn_goods_op_req {
                        goodsSku = product.Sku
                    };
                    var api_detail_result = await new HniaoMallSign().HniaoReq<hn_goods_op_res>(req);
                    if (api_detail_result.data != null) {
                        if (api_detail_result.data.goodsDetail.spec != null) {
                            decimal max_price = 0;
                            var temp_spec = new hn_goods_spec();
                            var item = JObject.Parse(api_detail_result.data.goodsDetail.spec.ToJson());
                            var collection = item.ToObject<SortedDictionary<string, object>>();
                            foreach (var kv in collection) {
                                if (kv.Value is JArray) {
                                    var arrs = kv.Value as JArray;
                                    foreach (var spec in arrs) {
                                        var goods_spec = spec.ToObject<hn_goods_spec>();
                                        if (goods_spec.specNum == 1 && goods_spec.specPrice > max_price) {
                                            temp_spec = goods_spec;
                                            max_price = goods_spec.specPrice;
                                        }
                                    }
                                }
                            }
                            order.goods.Add(new hn_goods {
                                goodsNum = order_item.Quantity.ToString(),
                                goodsPrice = temp_spec.specPrice,
                                goodsSpecNames = temp_spec.specDesc,
                                goodsSku = product.Sku,
                                goodsSpecNum = temp_spec.specNum,
                                startExpDate = temp_spec.startExpDate,
                                endExpDate = temp_spec.endExpDate
                            });
                        }
                    }
                }
                hnOrders.Add(order);
                var order_req = new hn_create_order_req {
                    orders = hnOrders.ToJson()
                };
                var order_result = await _hnMallSign.HniaoReq<hn_create_order_res>(order_req);
                if (order_result.code == "0") {
                    var push_order = context.Orders.FirstOrDefault(c => c.OrderNo == pay_html.order_no);
                    log.Info(string.Format("订单：{0}推送成功", pay_html.order_no));
                    if (order_result.successOrders.Count > 0) {
                        html.IsFinish = 1;
                        push_order.PushStatus = OrderPushStatus.Pushed;
                    } else if (order_result.errorOrders.Count > 0) {
                        var msg = order_result.errorOrders.First().message;
                        if (msg == "客户订单号已存在") {
                            push_order.PushStatus = OrderPushStatus.Pushed;
                            push_order.PushFailMsg = "推送成功";
                        } else {
                            log.Info(string.Format("订单：{0}推送失败", ord_html.OrderNo));
                            push_order.PushStatus = OrderPushStatus.PushFail;
                            push_order.PushFailMsg = msg;
                        }
                    }
                }
                log.Info(order.ToJson());
                result = _iUnitOfWork.Commit("PayHtml");
            }

            return result;
        }
        /// <summary>
        /// 根据单号推送
        /// </summary>
        /// <param name="order_no"></param>
        /// <returns></returns>
        public async Task<int> PushOrderBath(string order_no) {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("候鸟订单推送中...");
            bool isPush = false;
            int result = 0;
            var hnOrders = new List<hn_order>();
            var order = _iOrderService.Get(order_no);
            var regions = order.shipping.region_name.Split(' ');
            var hnOrder = new hn_order {
                userName = order.shipping.real_name,
                IDCard = order.shipping.id_card,
                userAddress = order.shipping.address,
                userPhone = order.shipping.phone,
                province = regions[0],
                city = regions[1],
                district = (regions.Length == 3 ? regions[2] : ""),
                realTotalMoney = order.pay_amount,
                createTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                cusOrderNo = order.order_no,
                goodsMoney = order.order_amount,
                deliverMoney = 0
            };
            foreach (var order_item in order.order_items) {
                var product = context.Products.FirstOrDefault(c => c.Id == order_item.product_id);
                var req = new hn_goods_op_req {
                    goodsSku = product.Sku
                };
                var api_detail_result = await new HniaoMallSign().HniaoReq<hn_goods_op_res>(req);
                if (api_detail_result.data != null) {
                    if (api_detail_result.data.goodsDetail.spec != null) {
                        decimal max_price = 0;
                        var temp_spec = new hn_goods_spec();
                        var item = JObject.Parse(api_detail_result.data.goodsDetail.spec.ToJson());
                        var collection = item.ToObject<SortedDictionary<string, object>>();
                        foreach (var kv in collection) {
                            if (kv.Value is JArray) {
                                var arrs = kv.Value as JArray;
                                foreach (var spec in arrs) {
                                    var goods_spec = spec.ToObject<hn_goods_spec>();
                                    if (goods_spec.specNum == 1 && goods_spec.specPrice > max_price) {
                                        temp_spec = goods_spec;
                                        max_price = goods_spec.specPrice;
                                    }
                                }
                            }
                        }
                        hnOrder.goods.Add(new hn_goods {
                            goodsNum = order_item.quantity.ToString(),
                            goodsPrice = temp_spec.specPrice,
                            goodsSpecNames = temp_spec.specDesc,
                            goodsSku = product.Sku,
                            goodsSpecNum = temp_spec.specNum,
                            startExpDate = temp_spec.startExpDate,
                            endExpDate = temp_spec.endExpDate
                        });
                    }
                }
            }
            hnOrders.Add(hnOrder);
            var order_req = new hn_create_order_req {
                orders = hnOrders.ToJson()
            };
            hn_create_order_res order_result = null;
            try {
                order_result = await _hnMallSign.HniaoReq<hn_create_order_res>(order_req);
            } catch { }
            if (order_result.code == "0") {
                var push_order = context.Orders.FirstOrDefault(c => c.OrderNo == order.order_no);
                log.Info(string.Format("订单：{0}推送成功", order.order_no));
                if (order_result.successOrders.Count > 0) {
                    push_order.PushStatus = OrderPushStatus.Pushed;
                    isPush = true;
                } else if (order_result.errorOrders.Count > 0) {
                    var msg = order_result.errorOrders.First().message;
                    if (msg == "客户订单号已存在") {
                        push_order.PushStatus = OrderPushStatus.Pushed;
                        push_order.PushFailMsg = "推送成功";
                        isPush = true;
                    } else {
                        log.Info(string.Format("订单：{0}推送失败", order.order_no));
                        push_order.PushStatus = OrderPushStatus.PushFail;
                        push_order.PushFailMsg = msg;
                    }
                }
            }
            log.Info(order.ToJson());
            result = _iUnitOfWork.Commit("PayHtml");
            return (isPush ? 1 : 0);
        }
        /// <summary>
        /// 查询订单物流信息
        /// </summary>
        /// <param name="order_no"></param>
        /// <returns></returns>
        public async Task<List<hn_expressInfo>> GetOrderExpress(string order_no) {
            var express_req = new hn_express_req {
                cusOrderNo = order_no
            };
            var express_result = await _hnMallSign.HniaoReq<hn_express_res>(express_req);
            if (express_result.code == "0") {
                return express_result.expressInfo;
            }
            return new List<hn_expressInfo>();
        }
        /// <summary>
        /// 查询订单状态
        /// </summary>
        /// <param name="order_no"></param>
        /// <returns></returns>
        public async Task<int> GetOrderStatus() {
            var merchant = _iMerchantService.Get(RequestMethod.HNIAO_NO);
            var query = new OrderQuery {
                merchant_id = merchant.id,
                order_status = OrderStatus.WaitDelivery,
                order_type = 2
            };
            var orders = _iOrderService.Gets(query);
            var ordersNo = orders.Select(c => c.OrderNo).ToList();
            foreach (var orderNo in ordersNo) {
                var order_req = new hn_query_order_status_req {
                    cusOrderNo = orderNo
                };
                var order_result = await _hnMallSign.HniaoReq<hn_query_order_status_res>(order_req);
                if (order_result.code == "0") {
                    foreach (var orderInfo in order_result.orderInfo) {
                        var order = context.Orders.FirstOrDefault(c => c.OrderNo == orderInfo.cusOrderNo);
                        if (order.Status == OrderStatus.WaitDelivery) {
                            if (orderInfo.orderStatus == 1) {
                                order.Status = OrderStatus.Confirm;
                                if (order_result.orderInfo.Count > 0) {
                                    order.Shipping.ExpressCompanyName = order_result.orderInfo[0].expressName;
                                    order.Shipping.ExpressNo = StringHelper.ReplaceExpressCode(order_result.orderInfo[0].expressCode);
                                    order.Shipping.ShipOrderNumber = order_result.orderInfo[0].expressNo;
                                    order.Shipping.ShippingTime = order_result.orderInfo[0].deliveryTime.ToUnix();
                                }
                            } else if (orderInfo.orderStatus == 2) {
                                order.Status = OrderStatus.Finish;
                            } else if (orderInfo.orderStatus == -1) {
                                order.Status = OrderStatus.Close;
                            }
                        }
                        int result = _iUnitOfWork.Commit(order.BuyId.HasValue ? "Orders" + order.BuyId.Value : "");
                    }
                }
            }
            return 0;
        }
    }
}
